﻿using System;
using System.Collections.Generic;
using System.Net;
using System.Threading;
using Microsoft.TeamFoundation.Client;
using TShooter.TfsSearch.Engine.Configuration;
using TShooter.TfsSearch.Engine.Properties;
using TShooter.TfsSearch.EngineModel;

namespace TShooter.TfsSearch.Engine
{
    public class ServerManager: IService
    {
        #region Constructors and member variables

        private readonly ICredentials _Credentials;
        private readonly string _Url;
        private TeamFoundationServer _Server;
        private readonly List<IEngine> _Engines = new List<IEngine>();
        private ThreadPriority _Priority;
        private int _CurrentEngine;

        public ServerManager(string url, string userName, string password)
            : this(url, new NetworkCredential(userName, password))
        {
        }

        public ServerManager(string url, ICredentials credentials)
        {
            _Url = url;
            _Credentials = credentials;
        }

        private void LoadEngines(EngineRegistrationCollection engines)
        {
            engines.Sort(delegate(EngineRegistration x, EngineRegistration y)
                             {
                                 return x.Priority.CompareTo(y.Priority);
                             });

            foreach (EngineRegistration reg in engines)
            {
                IEngine engine = EngineFactory.GetEngine(reg.EngineTypeName);
                engine.Server = Server;
                _Engines.Add(engine);
            }
        }

        public ServerManager(ServerRegistration registration)
            : this(registration.Url, registration.UserName, registration.Password)
        {
            LoadEngines(registration.Engines);
        }

        #endregion

        #region Event handlers

        void Engine_Finished(object sender, EventArgs e)
        {
            StartNextEngine();
        }

        #endregion

        #region IService Members

        public event EventHandler Finished;

        public string Name
        {
            get { return _Url; }
        }

        public bool IsActive
        {
            get { return CurrentEngine != null && CurrentEngine.IsActive; }
        }

        public void Start()
        {
            _CurrentEngine = -1;
            
            if (_Engines.Count > 0)
            {
                StartNextEngine();
            }
        }

        public void Stop()
        {
            if (IsActive)
            {
                CurrentEngine.Stop();
            }
            OnFinished();
        }

        public void Pause(int autoResumeMillisecs)
        {
            if (IsActive)
            {
                CurrentEngine.Pause(autoResumeMillisecs);
            }
        }

        public void Resume()
        {
            if (IsActive)
            {
                CurrentEngine.Resume();
            }
        }

        public ThreadPriority Priority
        {
            get { return _Priority; }
            set { _Priority = value; }
        }

        #endregion

        #region Properties

        private IEngine CurrentEngine
        {
            get
            {
                bool hasActiveEngine = _CurrentEngine >= 0 && _CurrentEngine < _Engines.Count;
                return hasActiveEngine? _Engines[_CurrentEngine]: null;
            }
        }

        private TeamFoundationServer Server
        {
            get
            {
                if (_Server == null)
                {
                    _Server = new TeamFoundationServer(_Url, _Credentials);
                }

                return _Server;
            }
        }

        #endregion

        #region Static methods

        public static ServerManagerCollection GetRegisteredServers()
        {
            ServerRegistrationCollection servers = Settings.Default.RegisteredServers;
            ServerManagerCollection ret = new ServerManagerCollection();

            if (servers == null || servers.Count == 0)
            {
                return ret;
            }

            foreach (ServerRegistration server in servers)
            {
                ret.Add(new ServerManager(server));
            }

            return ret;
        }

        #endregion

        #region Private methods

        private void StartNextEngine()
        {
            if (CurrentEngine != null)
            {
                CurrentEngine.Finished -= Engine_Finished;
            }

            if ((++_CurrentEngine) >= _Engines.Count)
            {
                Stop();
                return;
            }

            CurrentEngine.Finished += Engine_Finished;
            CurrentEngine.Start();
        }

        protected virtual void OnFinished()
        {
            if (Finished != null)
            {
                Finished(this, EventArgs.Empty);
            }
        }

        #endregion
    }

    public class ServerManagerCollection : List<ServerManager>
    {
    }
}